/* Copyright ©, 2022, ECARX (Hubei) Technology Co., Ltd. All rights reserved.
 *
 * NOTICE: This file contains information which is confidential and proprietary to ECARX
 * (Hubei) Technology Co., Ltd. and/or other developers. No license to any intellectual
 * property rights contained within this file is either granted or implied except as may be
 * provided in an agreement with ECARX (Hubei) Technology Co., Ltd.
 *
 * Any unauthorized copying or distribution of content from this file in whole or in part
 * is prohibited.
 */

#include <vhal_core/property/PropertyDecalary.h>

#include "IPropertyTransfer.h"
#include "vhal_core/property/IProperty.h"

namespace ecarx::vhal::core {
namespace impl::looper {
extern android::sp<android::Looper> mHandler;
}
namespace property {

class PropertyMessageHanlder : public android::MessageHandler {
    IProperty* mProperty;

  public:
    PropertyMessageHanlder(IProperty* property) : mProperty(property) {}
    ~PropertyMessageHanlder() {  }
    void handleMessage(const android::Message& message) override {
        if (mProperty != nullptr) {
            mProperty->executeTimer(message.what);
        }
    }
};

Property::Property(const int32_t propertyId, const char* proName,
                   VehiclePropertyChangeMode chanMode, VehiclePropertyAccess access)
    : mProperty(new IProperty(propertyId, proName, chanMode, access)),
      mMessageHandler(new PropertyMessageHanlder(mProperty)) {}

Property::~Property() {
    impl::looper::mHandler->removeMessages(mMessageHandler);
    delete mProperty;
    mProperty = nullptr;
}

void Property::init(IPropertyTransfer* transfer) {
    this->mTransfer = transfer;
    mProperty->registerWritePropValueListener(
        [transfer](const VehiclePropValue& value,CommitMode mode) { transfer->onPropertyValue(value,mode); });
}

IProperty* Property::toIProperty() {
    return mProperty;
}

void Property::sendMsg(uint32_t msgId, uint32_t delay_ms) {
    impl::looper::mHandler->sendMessageDelayed(milliseconds_to_nanoseconds(delay_ms),
                                               mMessageHandler, android::Message(msgId));
}

void Property::removeMsg(uint32_t msgId) {
    impl::looper::mHandler->removeMessages(mMessageHandler, msgId);
}

void Property::setPersistTyp(int32_t areaId, PersistType type) {
    Area* area = mProperty->getArea(areaId == toInt(VehicleArea::GLOBAL) ? 0 : areaId);
    area->setPersistType(type);
}

std::unique_ptr<VehiclePropValue> Property::getPropValue(int32_t propertyId, int32_t areaId) const {
    return mTransfer->getPropValue(propertyId, areaId);
}

bool Property::setPropValue(const VehiclePropValue& value) const {
    return mTransfer->setPropValue(value);
}

persist::DID* Property::getDID() {
    return mProperty->getDID();
}

persist::PlatformProfile* Property::getPlatformProfile() {
    return mProperty->getPlatformProfile();
}

int32_t Property::getCurrentProfileID() {
    auto platformProfile = mProperty->getPlatformProfile();
    if (platformProfile != nullptr) {
        auto profile = platformProfile->getCurrentProfile();
        if (profile != nullptr) {
            return profile->getProfileId();
        }
    }
    return 0;
}

PropertyStatus Property::getPropertyStatus(int32_t propertyId, int32_t areaId) const {
    auto value = getPropValue(propertyId, areaId);
    if (value != nullptr) {
        return PropertyStatus(static_cast<int32_t>(value->status));
    }
    return PropertyStatus::NotAvailable;
}

void Property::updateAreaStatus(int32_t areaId, PropertyStatus status) {
    auto area = mProperty->getArea(areaId == toInt(VehicleArea::GLOBAL) ? 0 : areaId);
    if (area != nullptr) {
        area->updateStatus(status);
    }
}

Area* Property::getArea(int32_t prop,int32_t areaId) const{
    return mTransfer->findArea(prop,areaId == toInt(VehicleArea::GLOBAL) ? 0 : areaId);
}

}  // namespace property
}  // namespace ecarx::vhal::core
